package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.IPointsRecordService;
import groovy.util.logging.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 *
 * @author elliehy
 * @since 2024-06-07
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {
	private final StringRedisTemplate redisTemplate;
	
	@Override
	public void addPointsRecord(Long userId, Integer points, PointsRecordType pointsRecordType) {
		//1.校验数据
		if (userId == null || points == null) {
			return;
		}
		int realPoints = points;
		//2.判断积分是否有上限  max>0则代表有上限
		if (pointsRecordType.getMaxPoints() > 0) {
			//3.如果有上限查询用户 该积分类型 今日已获得积分  points_record  条件userId type 今天 sum(points)
			//3.1获取今日的开始时间和结束时间
			LocalDateTime now = LocalDateTime.now();
			LocalDateTime dayStartTime = DateUtils.getDayStartTime(now);
			LocalDateTime dayEndTime = DateUtils.getDayEndTime(now);
			//3.2用mp查询
			Map<String, Object> map = this.getMap(new QueryWrapper<PointsRecord>()
					.select("sum(points) as totalPoints")
					.eq("user_id", userId)
					.eq("type", pointsRecordType)
					.between("create_time", dayStartTime, dayEndTime));
			int currentPoints = 0;
			if (map != null) {
				BigDecimal point = (BigDecimal) map.get("totalPoints");
				if (point != null) currentPoints = point.intValue();
			}
			//4.判断已获得积分是否超过上限
			if (currentPoints > pointsRecordType.getMaxPoints()) {
				//4.1说明已经达到上限
				return;
			}
			//4.2判断这次相加积分和已有积分是否超过上限
			if (currentPoints + points > pointsRecordType.getMaxPoints()) {
				realPoints = pointsRecordType.getMaxPoints() - currentPoints;
			}
		}
		//5.保存积分
		PointsRecord record = new PointsRecord();
		record.setUserId(userId);
		record.setType(pointsRecordType);
		record.setPoints(realPoints);
		this.save(record);
		
		//6.累加并保存总积分到Redis中 采用zSet结构 当前赛季的排行榜
		//6.1凭借KEY
		LocalDateTime now = LocalDateTime.now();
		String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
		String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;
		redisTemplate.opsForZSet().incrementScore(key, userId.toString(), realPoints);
	}
	
	@Override
	public List<PointsStatisticsVO> queryMyPointsToday() {
		//1.获取登录用户
		Long userId = UserContext.getUser();
		//2.查询积分表points_record  条件:userId  今日,  按照type分组  sum(point)
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime dayStartTime = DateUtils.getDayStartTime(now);
		LocalDateTime dayEndTime = DateUtils.getDayEndTime(now);
		List<PointsRecord> list = this.list(new QueryWrapper<PointsRecord>()
				.select("type", "sum(points) as userId")
				.eq("user_id", userId)
				.between("create_time", dayStartTime, dayEndTime)
				.groupBy("type"));
		if (CollUtils.isEmpty(list)) {
			return CollUtils.emptyList();
		}
		//3.封装VO返回
		return list.stream().map(l -> {
			PointsStatisticsVO vo = new PointsStatisticsVO();
			vo.setType(l.getType().getDesc());//获取积分类型的中文
			vo.setPoints(l.getUserId().intValue());
			vo.setMaxPoints(l.getType().getMaxPoints());
			return vo;
		}).collect(Collectors.toList());
	}
}
